上一次我們完成了簡陋的首頁,現在我們來解決按下Register會404的問題。
我們在AuthController.java中添加
//顯示註冊頁面
@GetMapping("/register")
public String register(Model model) {
User user = new User();
model.addAttribute("user", user);
return "register";
}
這樣我們就能進入註冊頁面。
接著處理註冊頁面顯示的內容,新增register.html,用來顯示註冊表單,如果已經註冊了可以點選切換到登入頁面。
//register.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>User Registration System</title>
</head>
<body>
<div>
<div>
<a th:href="@{/}">Home</a>
<a th:href="@{/login}">Login</a>
</div>
<div>
<form method="post" role="form" th:action="@{/register}" th:object="${user}">
<div>
<label>User Email</label>
<input placeholder="Enter user email" type="text" th:field="*{email}" />
<p th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></p>
</div>
<div>
<label>User Password</label>
<input placeholder="Enter user password" type="text" th:field="*{password}" />
<p th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></p>
</div>
<button type="submit">Register</button>
<span>Already registered? <a th:href="@{/login}">Login</a></span>
</form>
</div>
</div>
</body>
</html>
啟動專案,進入註冊頁面,目前註冊功能尚未實作。
在AuthController.java添加註冊處理,並驗證內容的格式
private final UserService userService;
public AuthController(UserService userService) {
this.userService = userService;
}
處理註冊
@PostMapping("/register")
public String saveUser(Model model,
@Valid @ModelAttribute("user") User user,
BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
model.addAttribute("user", user);
return "register";
}
userService.createUser(user);
return "redirect:/";
}
我們需要UserService.java將註冊的用戶資料儲存到資料庫中。
//UserService.java
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void createUser(User user) {
userRepository.save(user);
}
}
啟動專案,在註冊表單填入email和密碼後送出,打開MySQL Client (MariaDB 11.4 (x64))登入,輸入以下指令
USE user_db;
select * from users;
USE user_db:選擇user_db,讓接下來的指令都是在操作這個資料庫。
select * from users:傳回users資料表中的所有數據。
可以看到我們剛才輸入的內容。
現在我們嘗試再次輸入相同的email來註冊,會出現500錯誤,因為在entity的email欄位,我們有設定unique = true代表不能重複。
我們要來解決顯示500錯誤的問題,當email已經註冊了,會在前端顯示錯誤訊息,而不是500錯誤。
我們在UserRepository.java,添加
public interface UserRepository extends JpaRepository<User, Long> {
User findUserByEmail(String email);
}
這樣我們才能使用email查詢用戶。
在UserService.java,加入
public User getUserByEmail(String email) {
return userRepository.findUserByEmail(email);
}
我們就能在AuthController.java中用這個搜尋有沒有人用過這個email
我們在AuthController.java的saveUser部分添加程式碼。
查詢有沒有用戶使用這個email,如果已經有人用了,就顯示錯誤訊息
@PostMapping("/register")
public String saveUser(...) {
User userExisting = userService.getUserByEmail(user.getEmail());
if(userExisting != null) {
bindingResult.rejectValue("email", null, "email已註冊");
}
...
}
現在填入相同的email會顯示錯誤訊息了。
這種前端沒有做驗證就往後端傳送不符資料庫規定的資料,在團隊開發中常常發生,負責後端的人認為前端應該會驗證過在傳過來,負責前端的人認為後端會驗證內容,所以就直接傳送不符規定的內容。
到了發生錯誤時,前端就會表示那是後端要做的事,後端認為前端應該要驗證,而發生爭執。
最理想的狀態是前端後端都應該做驗證,或者前端後端互相溝通,提前確認分工。